package com.xyy.saas.payment.merchant.core.dto;

import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.common.enums.PictureEnum;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.*;
import com.xyy.saas.payment.cores.param.MerchantAccountModifyParam;
import com.xyy.saas.payment.cores.vo.BeneficiaryInfoVo;
import com.xyy.saas.payment.cores.vo.OperatorInfo;
import com.xyy.saas.payment.cores.vo.ShareHolderInfoVo;
import com.xyy.saas.payment.dao.model.ApplyAccountModify;
import com.xyy.saas.payment.merchant.core.vo.UserInfoVo;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.DateUtil;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import util.AESUtil;
import java.util.*;

@Getter
@Setter
public class MerchantAccountModifyDto {
    /**
     * 基础信息
     */
    // 业务线
    private BusinessIdTypeEnum businessIdType;
    // 业务侧商户标识
    private String businessId;
    // 回调地址
    private String callback;
    // 鉴权类型
    private InvokerEnum invoker;

    // 申请单号（业务不传）
    private String applyNo;
    // 支付平台侧商户标识（业务不传）
    private String accountId;
    // 申请来源 open_account,modify_account
    private String source = Constants.SOURCE_MODIFY_ACCOUNT;

    // 验证手机号，授权人手机号
    private String mobile;

    /**
     * 企业信息
     */
    // 企业电话
    private String enterprisePhone;
    // 经营地址
    private String businessLocation;
    // 门头照
    private String businessLocationUrl;
    // 营业执照
    private String businessLicenseUrl;

    /**
     * 法人信息
     */
    // 法人姓名
    private String corporationName;
    // 法人身份证号
    private String corporationIdNo;
    // 法人证件签发日期
    private String corporationIdStartDate;
    // 法人证件到期日期
    private String corporationIdEndDate;
    // 法人身份证正面
    private String corporationIdCardFrontUrl;
    // 法人身份证反面
    private String corporationIdCardBackUrl;
    // 法人联系电话
    private String corporationPhone;

    /**
     * 授权人
     */
    // 授权人姓名
    private String operatorName;
    // 授权人身份证号
    private String operatorIdNo;
    // 授权人手机号
    private String operatorPhone;
    // 业务授权函
    private String operatorCertificateUrl;

    /**
     * 股东
     */
    // 股东名称
    private String shareholderName;
    // 股东证件类型 IDENTITY_CARD UNIFIED_SOCIAL_CREDIT_CODE
    private String shareholderCardType;
    // 股东证件号码
    private String shareholderCardNo;
    // 股东证件签发日期 yyyy-MM-dd
    private String shareholderCardStartDate;
    // 股东证件到期日期 yyyy-MM-dd
    private String shareholderCardEndDate;

    /**
     * 受益人
     */
    // 受益人姓名
    private String beneficiaryName;
    // 受益人证件类型(只支持二代身份证)
    private String beneficiaryCardType = "IDENTITY_CARD";
    // 受益人身份证号
    private String beneficiaryCardNo;
    // 受益人证件签发日期
    private String beneficiaryCardStartDate;
    // 受益人证件到期日期
    private String beneficiaryCardEndDate;
    // 受益人联系电话
    private String beneficiaryPhone;
    // 受益人地址
    private String beneficiaryLocation;

    /**
     * 短信验证码
     */
    private String activeCode;

    /**
     * 审核信息
     */
    // 申请时间
    private String applyTime;
    // 审核时间
    private String auditTime;
    // 审核状态，com.xyy.saas.payment.cores.enums.AccountModifyStatusEnum
    private Integer status;
    // 驳回原因
    private String message;

    /**
     * 参数转换(param -> dto)
     */
    public static MerchantAccountModifyDto transfer(MerchantAccountModifyParam source) {
        // copy
        MerchantAccountModifyDto target = new MerchantAccountModifyDto();

        if(source != null) {
            BeanUtils.copyProperties(source, target);
        }

        return target;
    }

    /**
     * 参数转换(dto -> param)
     */
    public static MerchantAccountModifyParam transfer(MerchantAccountModifyDto source) {
        // copy
        MerchantAccountModifyParam target = new MerchantAccountModifyParam();

        if(source != null) {
            BeanUtils.copyProperties(source, target);
        }

        return target;
    }

    /**
     * 参数转换(dto -> param)
     */
    public static List<MerchantAccountModifyParam> transferParam(List<MerchantAccountModifyDto> items) {
        if(CollectionUtils.isEmpty(items)) {
            return null;
        }

        List<MerchantAccountModifyParam> result = new ArrayList<>();

        for(MerchantAccountModifyDto source : items) {
            result.add(transfer(source));
        }

        return result;
    }

    /**
     * 参数转换(dto -> domain)
     */
    public ApplyAccountModify transfer() throws Exception {
        ApplyAccountModify applyAccountModify = new ApplyAccountModify();
        applyAccountModify.setApplyNo(applyNo);
        applyAccountModify.setAccountId(accountId);
        applyAccountModify.setBusinessIdType(businessIdType.getType());
        applyAccountModify.setStatus(AccountModifyStatusEnum.CREATE.getStatus());
        applyAccountModify.setMessage(AccountModifyStatusEnum.CREATE.getDesc());
        applyAccountModify.setCallback(callback);
        applyAccountModify.setType(Constants.MERCHANT);
        applyAccountModify.setSource(source);
        applyAccountModify.setMobile(AESUtil.encrypt(getMobile(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applyAccountModify.setEnterpriseInfo(AESUtil.encrypt(getEnterprise(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applyAccountModify.setCorporationInfo(AESUtil.encrypt(getCorporation(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applyAccountModify.setOperatorInfo(AESUtil.encrypt(getOperator(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applyAccountModify.setShareholderInfo(AESUtil.encrypt(getShareholder(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applyAccountModify.setBeneficiaryInfo(AESUtil.encrypt(getBeneficiary(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        return applyAccountModify;
    }

    /**
     * 参数转换（domain -> dto）
     */
    public static MerchantAccountModifyDto transfer(ApplyAccountModify source) throws Exception {
        if(source == null) {
            return null;
        }

        MerchantAccountModifyDto result = new MerchantAccountModifyDto();
        result.setApplyNo(source.getApplyNo());
        result.setAccountId(source.getAccountId());
        result.setBusinessIdType(BusinessIdTypeEnum.type(source.getBusinessIdType()));
        result.setCallback(source.getCallback());
        result.setSource(source.getSource());
        result.setMobile(AESUtil.decrypt(source.getMobile(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        result.setEnterprise(AESUtil.decrypt(source.getEnterpriseInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        result.setCorporation(AESUtil.decrypt(source.getCorporationInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        result.setOperator(AESUtil.decrypt(source.getOperatorInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        result.setShareholder(AESUtil.decrypt(source.getShareholderInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        result.setBeneficiary(AESUtil.decrypt(source.getBeneficiaryInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        result.setApplyTime(DateUtil.format(source.getCreateTime(), DateUtil.DATEFORMATSECOND));
        result.setAuditTime(DateUtil.format(source.getUpdateTime(), DateUtil.DATEFORMATSECOND));
        result.setStatus(source.getStatus());
        result.setMessage(source.getMessage());
        return result;
    }

    /**
     * 参数转换（domain -> dto）
     */
    public static List<MerchantAccountModifyDto> transfer(List<ApplyAccountModify> items, String businessId) throws Exception {
        if(CollectionUtils.isEmpty(items)) {
            return null;
        }

        List<MerchantAccountModifyDto> result = new ArrayList<>();

        for(ApplyAccountModify source : items) {
            MerchantAccountModifyDto item = transfer(source);
            item.setBusinessId(businessId);
            result.add(item);
        }

        return result;
    }
    /**
     * 更新覆盖user_info信息
     */
    public void copy2UserInfo(UserInfoVo userInfoVo) {
        // 图片
        if(StringUtils.isNotBlank(businessLocationUrl)) {
            userInfoVo.getPicInfo().put(String.valueOf(PictureEnum.SHOP_ENTRANCE_PIC.getCode()), businessLocationUrl);
        }

        if(StringUtils.isNotBlank(businessLicenseUrl)) {
            userInfoVo.getPicInfo().put(String.valueOf(PictureEnum.BUSINESS_CERT_PIC.getCode()), businessLicenseUrl);
        }

        if(StringUtils.isNotBlank(corporationIdCardFrontUrl)) {
            userInfoVo.getPicInfo().put(String.valueOf(PictureEnum.LEGAL_CERT_FRONT.getCode()), corporationIdCardFrontUrl);
        }

        if(StringUtils.isNotBlank(corporationIdCardBackUrl)) {
            userInfoVo.getPicInfo().put(String.valueOf(PictureEnum.LEGAL_CERT_BACK.getCode()), corporationIdCardBackUrl);
        }

        // 法人
        if(StringUtils.isNotBlank(corporationName) && StringUtils.isNotBlank(corporationIdNo)) {
            userInfoVo.getContactInfo().get(NumberUtils.INTEGER_ZERO).setContactName(corporationName);
            userInfoVo.getContactInfo().get(NumberUtils.INTEGER_ZERO).setContactCertNo(corporationIdNo);
            userInfoVo.getContactInfo().get(NumberUtils.INTEGER_ZERO).setContactCertValidFrom(corporationIdStartDate);
            userInfoVo.getContactInfo().get(NumberUtils.INTEGER_ZERO).setContactCertValidFrom(corporationIdEndDate);

            if(StringUtils.isNotBlank(corporationPhone)) {
                userInfoVo.getContactInfo().get(NumberUtils.INTEGER_ZERO).setContactCertMobile(corporationPhone);
            }
        }

        // 企业
        if(StringUtils.isNotBlank(businessLocation)) {
            userInfoVo.getBasicInfo().setAddress(businessLocation);
        }

        if(StringUtils.isNotBlank(enterprisePhone)) {
            userInfoVo.getBasicInfo().getIdentityInfo().setPhone(enterprisePhone);
        }

        // 操作人
        if(StringUtils.isNotBlank(operatorName) &&
                StringUtils.isNotBlank(operatorIdNo) &&
                StringUtils.isNotBlank(operatorPhone))
        {
            OperatorInfo operatorInfo = new OperatorInfo();
            operatorInfo.setName(operatorName);
            operatorInfo.setCardNo(operatorIdNo);
            operatorInfo.setPhone(operatorPhone);
            operatorInfo.setCertificateUrl(operatorCertificateUrl);
            userInfoVo.setOperatorInfo(operatorInfo);
        }

        // 股东
        if(StringUtils.isNotBlank(shareholderName) && StringUtils.isNotBlank(shareholderCardNo)) {
            ShareHolderInfoVo shareHolderInfo = new ShareHolderInfoVo();
            shareHolderInfo.setShareHolderName(shareholderName);
            shareHolderInfo.setShareHolderCardType(shareholderCardType);
            shareHolderInfo.setShareHolderCardNo(shareholderCardNo);
            shareHolderInfo.setShareHolderCardStartDate(shareholderCardStartDate);
            shareHolderInfo.setShareHolderCardEndDate(shareholderCardEndDate);
            userInfoVo.setShareHolderInfo(shareHolderInfo);
        }

        // 受益人
        if(StringUtils.isNotBlank(beneficiaryName) && StringUtils.isNotBlank(beneficiaryCardNo)) {
            BeneficiaryInfoVo beneficiaryInfo = new BeneficiaryInfoVo();
            beneficiaryInfo.setBeneficiaryName(beneficiaryName);
            beneficiaryInfo.setBeneficiaryCardType(beneficiaryCardType);
            beneficiaryInfo.setBeneficiaryCardNo(beneficiaryCardNo);
            beneficiaryInfo.setBeneficiaryCardStartDate(beneficiaryCardStartDate);
            beneficiaryInfo.setBeneficiaryCardEndDate(beneficiaryCardEndDate);
            beneficiaryInfo.setBeneficiaryPhone(beneficiaryPhone);
            beneficiaryInfo.setBeneficiaryLocation(beneficiaryLocation);
            userInfoVo.setBeneficiaryInfo(beneficiaryInfo);
        }

        // 审核状态
        userInfoVo.setAuditStatus(AccountCreateStatusEnum.PASS.getStatus());
        userInfoVo.setMessage(AccountCreateStatusEnum.PASS.getDesc());

        // 更新时间
        userInfoVo.setUtime(DateUtil.now());
    }

    private String getEnterprise() {
        JSONObject enterprise = new JSONObject();

        if(StringUtils.isNotBlank(enterprisePhone)) {
            enterprise.put("enterprisePhone", enterprisePhone);
        }

        if(StringUtils.isNotBlank(businessLocation)) {
            enterprise.put("businessLocation", businessLocation);
        }

        if(StringUtils.isNotBlank(businessLocationUrl)) {
            enterprise.put("businessLocationUrl", businessLocationUrl);
        }

        if(StringUtils.isNotBlank(businessLicenseUrl)) {
            enterprise.put("businessLicenseUrl", businessLicenseUrl);
        }

        return enterprise.toJSONString();
    }

    private void setEnterprise(String enterprise) {
        if(StringUtils.isBlank(enterprise)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(enterprise);
        setEnterprisePhone(object.getString("enterprisePhone"));
        setBusinessLocation(object.getString("businessLocation"));
        setBusinessLocationUrl(object.getString("businessLocationUrl"));
        setBusinessLicenseUrl(object.getString("businessLicenseUrl"));
    }

    private String getCorporation() {
        JSONObject corporation = new JSONObject();

        if(StringUtils.isNotBlank(corporationName)) {
            corporation.put("corporationName", corporationName);
        }

        if(StringUtils.isNotBlank(corporationIdNo)) {
            corporation.put("corporationIdNo", corporationIdNo);
        }

        if(StringUtils.isNotBlank(corporationIdStartDate)) {
            corporation.put("corporationIdStartDate", corporationIdStartDate);
        }

        if(StringUtils.isNotBlank(corporationIdEndDate)) {
            corporation.put("corporationIdEndDate", corporationIdEndDate);
        }

        if(StringUtils.isNotBlank(corporationIdCardFrontUrl)) {
            corporation.put("corporationIdCardFrontUrl", corporationIdCardFrontUrl);
        }

        if(StringUtils.isNotBlank(corporationIdCardBackUrl)) {
            corporation.put("corporationIdCardBackUrl", corporationIdCardBackUrl);
        }

        if(StringUtils.isNotBlank(corporationPhone)) {
            corporation.put("corporationPhone", corporationPhone);
        }

        return corporation.toJSONString();
    }

    private void setCorporation(String corporation) {
        if(StringUtils.isBlank(corporation)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(corporation);
        setCorporationName(object.getString("corporationName"));
        setCorporationIdNo(object.getString("corporationIdNo"));
        setCorporationIdStartDate(object.getString("corporationIdStartDate"));
        setCorporationIdEndDate(object.getString("corporationIdEndDate"));
        setCorporationIdCardFrontUrl(object.getString("corporationIdCardFrontUrl"));
        setCorporationIdCardBackUrl(object.getString("corporationIdCardBackUrl"));
        setCorporationPhone(object.getString("corporationPhone"));
    }

    private String getOperator() {
        JSONObject operator = new JSONObject();

        if(StringUtils.isNotBlank(operatorName)) {
            operator.put("operatorName", operatorName);
        }

        if(StringUtils.isNotBlank(operatorIdNo)) {
            operator.put("operatorIdNo", operatorIdNo);
        }

        if(StringUtils.isNotBlank(operatorPhone)) {
            operator.put("operatorPhone", operatorPhone);
        }

        if(StringUtils.isNotBlank(operatorCertificateUrl)) {
            operator.put("operatorCertificateUrl", operatorCertificateUrl);
        }

        return operator.toJSONString();
    }

    private void setOperator(String operator) {
        if(StringUtils.isBlank(operator)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(operator);
        setOperatorName(object.getString("operatorName"));
        setOperatorIdNo(object.getString("operatorIdNo"));
        setOperatorPhone(object.getString("operatorPhone"));
        setOperatorCertificateUrl(object.getString("operatorCertificateUrl"));
    }

    private String getShareholder() {
        JSONObject shareholder = new JSONObject();

        if(StringUtils.isNotBlank(shareholderName)) {
            shareholder.put("shareholderName", shareholderName);
        }

        if(StringUtils.isNotBlank(shareholderCardType)) {
            shareholder.put("shareholderCardType", shareholderCardType);
        }

        if(StringUtils.isNotBlank(shareholderCardNo)) {
            shareholder.put("shareholderCardNo", shareholderCardNo);
        }

        if(StringUtils.isNotBlank(shareholderCardStartDate)) {
            shareholder.put("shareholderCardStartDate", shareholderCardStartDate);
        }

        if(StringUtils.isNotBlank(shareholderCardEndDate)) {
            shareholder.put("shareholderCardEndDate", shareholderCardEndDate);
        }

        return shareholder.toJSONString();
    }

    private void setShareholder(String shareholder) {
        if(StringUtils.isBlank(shareholder)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(shareholder);
        setShareholderName(object.getString("shareholderName"));
        setShareholderCardType(object.getString("shareholderCardType"));
        setShareholderCardNo(object.getString("shareholderCardNo"));
        setShareholderCardStartDate(object.getString("shareholderCardStartDate"));
        setShareholderCardEndDate(object.getString("shareholderCardEndDate"));
    }

    private String getBeneficiary() {
        JSONObject beneficiary = new JSONObject();

        if(StringUtils.isNotBlank(beneficiaryName)) {
            beneficiary.put("beneficiaryName", beneficiaryName);
        }

        if(StringUtils.isNotBlank(beneficiaryCardType)) {
            beneficiary.put("beneficiaryCardType", beneficiaryCardType);
        }

        if(StringUtils.isNotBlank(beneficiaryCardNo)) {
            beneficiary.put("beneficiaryCardNo", beneficiaryCardNo);
        }

        if(StringUtils.isNotBlank(beneficiaryCardStartDate)) {
            beneficiary.put("beneficiaryCardStartDate", beneficiaryCardStartDate);
        }

        if(StringUtils.isNotBlank(beneficiaryCardEndDate)) {
            beneficiary.put("beneficiaryCardEndDate", beneficiaryCardEndDate);
        }

        if(StringUtils.isNotBlank(beneficiaryPhone)) {
            beneficiary.put("beneficiaryPhone", beneficiaryPhone);
        }

        if(StringUtils.isNotBlank(beneficiaryLocation)) {
            beneficiary.put("beneficiaryLocation", beneficiaryLocation);
        }

        return beneficiary.toJSONString();
    }

    private void setBeneficiary(String beneficiary) {
        if(StringUtils.isBlank(beneficiary)) {
            return;
        }

        JSONObject object = JSONObject.parseObject(beneficiary);
        setBeneficiaryName(object.getString("beneficiaryName"));
        setBeneficiaryCardType(object.getString("beneficiaryCardType"));
        setBeneficiaryCardNo(object.getString("beneficiaryCardNo"));
        setBeneficiaryCardStartDate(object.getString("beneficiaryCardStartDate"));
        setBeneficiaryCardEndDate(object.getString("beneficiaryCardEndDate"));
        setBeneficiaryPhone(object.getString("beneficiaryPhone"));
        setBeneficiaryLocation(object.getString("beneficiaryLocation"));
    }

    /**
     * 参数校验
     */
    public void checkParam() throws PaymentException {
        if(businessIdType == null) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "业务线（businessIdType）不能为空");
        }

        if(StringUtils.isBlank(businessId)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "商户标识（businessId）不能为空");
        }

        if(StringUtils.isBlank(callback)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "回调（callback）不能为空");
        }

        if(StringUtils.isBlank(mobile)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "验证手机号（mobile）不能为空");
        }

        if(StringUtils.isBlank(activeCode)) {
            throw new PaymentException(ResultCodeEnum.PARAM_ERROR.getCode(), "验证码（activeCode）不能为空");
        }
    }

    /**
     * 股东
     * @return
     */
    public List<Map<String, String>> getShareHolderList() {
        if(getShareholderName() == null || getShareholderCardNo() == null ||
                getShareholderCardStartDate() == null || getShareholderCardEndDate() == null)
        {
            return null;
        }

        List<Map<String, String>> shareHolderList = new ArrayList<>();

        Map<String, String> shMap = new HashMap<>();
        shMap.put("name", getShareholderName());

        if(CertTypeEnum.ID_CARD.getCode().equals(getShareholderCardType())) {
            shMap.put("cardType", "IDENTITY_CARD");
        }
        else {
            shMap.put("cardType", "UNIFIED_SOCIAL_CREDIT_CODE");
        }

        shMap.put("cardNo", getShareholderCardNo());
        shMap.put("cardStartDate", getShareholderCardStartDate());
        shMap.put("cardEndDate", getShareholderCardEndDate());
        shareHolderList.add(shMap);

        return shareHolderList;
    }

    /**
     * 受益人
     */
    public List<Map<String, String>> getBeneficiaryList() {
        if(getBeneficiaryName() == null || getBeneficiaryCardType() == null ||
                getBeneficiaryCardNo() == null || getBeneficiaryCardStartDate() == null ||
                getBeneficiaryCardEndDate() == null || getBeneficiaryPhone() == null ||
                getBeneficiaryLocation() == null)
        {
            return null;
        }

        List<Map<String, String>> beneficiaryList = new ArrayList<>();

        Map<String, String> beMap = new HashMap<>();
        beMap.put("name", getBeneficiaryName());
        beMap.put("cardType", "IDENTITY_CARD");
        beMap.put("cardNo", getBeneficiaryCardNo());
        beMap.put("cardStartDate", getBeneficiaryCardStartDate());
        beMap.put("cardEndDate", getBeneficiaryCardEndDate());
        beMap.put("phone", getBeneficiaryPhone());
        beMap.put("location", getBeneficiaryLocation());
        beneficiaryList.add(beMap);

        return beneficiaryList;
    }
}
